/**
* Pimp your Flex app using WSBackgroundPixelSkin [without images - pure CSS and AS]
* 
* @author    Jens Krause [www.websector.de]
* @update    07/10/07
* @see        http://www.websector.de/blog/2007/07/06/pimp-your-flex-app-using-wsbackgroundpixelskin/
* 
* Feel free to use the source - its licensed under the Mozilla Public License 1.1. (http://www.mozilla.org/MPL/MPL-1.1.html)
* 
*/

package com.ws
{

    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.geom.Rectangle;
    import flash.utils.getTimer;
    
    import mx.skins.ProgrammaticSkin;
    
    
    [Style(name="bgPattern", type="Array", format="Array", inherit="no")]
    [Style(name="bgColors", type="Array", format="Number", inherit="no")]
    [Style(name="bgPixelMeasure", type="uint", format="Number", inherit="no")]
	[Style(name="topLeftCornerRadius", type="Number", inherit="no")]
	[Style(name="topRightCornerRadius", type="Number", inherit="no")]
	[Style(name="lowerLeftCornerRadius", type="Number", inherit="no")]
	[Style(name="lowerRightCornerRadius", type="Number", inherit="no")]
    [Style(name="backgroundAlpha", type="Number", inherit="no")]            
    
    public class WSBackgroundPixelSkin extends ProgrammaticSkin
    {
        private var _bgPattern: Array = [0, 1];
        private var _bgColors: Array = [0];
        private var _bgPixelMeasure: uint = 10;
        
        private var _bgBitmapData: BitmapData;
        private var _bgBitmap: Bitmap;
        private var _patternBitmapData: BitmapData;

        private var _patternWidth: uint;
        private var _patternHeight: uint;
        
        private var _styleNameChanged: Boolean = true;
        private var _bgPatternChanged: Boolean = true;
        private var _bgColorsChanged: Boolean = true;
        private var _bgPixelMeasureChanged: Boolean = true;        
        private var _patternChanged: Boolean = true;
        
        private var _lastUnscaledWidth:Number;
        private var _lastUnscaledHeight:Number;
        
        private var tlr : Number;
        private var trr : Number;			
        private var llr : Number;		
        private var lrr : Number;        
                            
        public function WSBackgroundPixelSkin()
        {
            super();
        }

        /**
         * Overrides styleChanged() to detect changes style definitions 
         * @param styleProp        The name of the style property
         * 
         */        
        override public function styleChanged(styleProp: String):void 
        {
            super.styleChanged(styleProp);         
            
            switch (styleProp)
            {
                case "bgPattern":
                    _bgPatternChanged = true;
                    invalidateDisplayList();
                    break
                case "bgColors":
                    _bgColorsChanged = true;
                    invalidateDisplayList();
                    break
                case "bgPixelMeasure":
                    _bgPixelMeasureChanged = true;
                    invalidateDisplayList();
                    break
                case "styleName":
                    _styleNameChanged = true;
                    invalidateDisplayList();
                	break;
                default:            
            }              
            
            tlr = getStyle("topLeftCornerRadius") as Number
        	if ( !tlr ) tlr = 0;
        	
        	trr = getStyle( "topRightCornerRadius" ) as Number
        	if ( !trr ) trr = 0;
        	
        	llr = getStyle( "lowerLeftCornerRadius" ) as Number
        	if ( !llr ) llr = 0;
        	
        	lrr = getStyle( "lowerRightCornerRadius" ) as Number
        	if ( !lrr ) lrr = 0;
            
            
        } 
        
        /**
         * Overrides updateDisplayList() to update the component based on the style setting 
         * @param unscaledWidth        height of the component
         * @param unscaledHeight    width of the component
         * 
         */            
        override protected function updateDisplayList(unscaledWidth: Number, unscaledHeight: Number):void
        {            
            this.alpha = getStyle("backgroundAlpha") as Number;
            var redrawWallpaper:Boolean = false;
            //
            // check to see if style "bgPattern" changed
            if (_bgPatternChanged) 
            {
                _bgPattern = (getStyle("bgPattern") is Array) ? getStyle("bgPattern") : [getStyle("bgPattern")];
                _patternChanged = true;
                _bgPatternChanged = false;
                redrawWallpaper = true;
            }
            //
            // check to see if style "bgColors" changed
            if (_bgColorsChanged)  
            {
                _bgColors = getStyle("bgColors");
                _patternChanged = true;
                _bgColorsChanged = false;                
                redrawWallpaper = true;
            }
            //
            // check to see if style "bgPixelMeasure" changed            
            if (_bgPixelMeasureChanged) 
            {
                _bgPixelMeasure = Number(getStyle("bgPixelMeasure"));
                _patternChanged = true;    
                _bgPixelMeasureChanged = false;            
                redrawWallpaper = true;
            }                                                    
            //
            // check to see if new "styleName" or styles above changed            
            if (_patternChanged || _styleNameChanged) 
            {
                createPattern();
                _patternChanged = false;
                _styleNameChanged = false;
                redrawWallpaper = true;
            }

			if (unscaledHeight != _lastUnscaledHeight || unscaledWidth != _lastUnscaledWidth) {
                redrawWallpaper = true;
			}
            //
            // draw wallpaper on valid height and width only        
            if (height > 0 && width > 0 && redrawWallpaper) {
							_lastUnscaledHeight = unscaledHeight;
							_lastUnscaledWidth = unscaledWidth;
            	drawWallpaper(unscaledWidth, unscaledHeight);            
            }
            
        }
        
        /**
         * Creates a bitmap pattern based on style definition
         * when styles changed only
         * 
         */        
        private function createPattern():void
        {
            _patternWidth = _bgPattern[0].length * _bgPixelMeasure;
            _patternHeight = _bgPattern.length * _bgPixelMeasure;
            
            if (_patternBitmapData) _patternBitmapData.dispose();
            
            _patternBitmapData = new BitmapData(_patternWidth, _patternHeight, false, 0);        
        
            for (var i: uint = 0; i < _bgPattern.length; i++)
            {
                for (var j: uint = 0; j < _bgPattern[i].length; j++)
                {
                    var rect: Rectangle = new Rectangle(_bgPixelMeasure * j, 
                                                        _bgPixelMeasure * i, 
                                                        _bgPixelMeasure, 
                                                        _bgPixelMeasure);
                    
                    var colorIndex: String = _bgPattern[i].charAt(j);
                    // parse color based on hexadec. values (0-F)
                    _patternBitmapData.fillRect(rect, _bgColors[parseInt("0x" + colorIndex)]);                    
                }
            }
        }

        /**
         * Draws a wallpaper based on its bitmap pattern 
         *  
         */            
        private function drawWallpaper(unscaledWidth: Number, unscaledHeight: Number):void
        {
        	var startTime:int = getTimer();
            var _tlr : Number = Math.max( tlr-2, 0 );
           	var _trr : Number = Math.max( trr-2, 0 );
           	var _llr : Number = Math.max( llr-2, 0 );
           	var _lrr : Number = Math.max( lrr-2, 0 );
            this.graphics.clear();
            this.graphics.beginBitmapFill(_patternBitmapData);
            this.graphics.moveTo(0,0);
            this.graphics.drawRoundRectComplex(0,0,unscaledWidth, unscaledHeight, _tlr, _trr, _llr, _lrr);
            this.graphics.endFill();
        }
    }    
}

